package com.tianji.learning.handler;

import com.tianji.common.utils.CollUtils;
import com.tianji.learning.constants.LearningConstants;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.domain.po.PointsBoardSeason;
import com.tianji.learning.controller.service.IPointsBoardSeasonService;
import com.tianji.learning.controller.service.IPointsBoardService;
import com.tianji.learning.utils.TableInfoContext;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Component
@RequiredArgsConstructor
public class PointsBoardPersistentHandler {
    private final IPointsBoardSeasonService seasonService;
    private final RedisTemplate redisTemplate;
    private final IPointsBoardService pointsBoardService;
    @XxlJob("createTableJob")//注解中定义的是当前如任务的名字
    public void createPointsBoardTableOfLastSeason(){
        //1.获取上月的当前时间，当前月份减去1个月就是上月
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        //2.查询赛季id 条件 begin_time <= time and end_time >= time
        PointsBoardSeason one = seasonService.lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, time)
                .ge(PointsBoardSeason::getEndTime, time)
                .one();
        if(one==null){
            //赛季不存在
            return;
        }
        //3.创建表
        pointsBoardService.createPointsBoardTableBySeason(one.getId());
    }
    //持久化上赛季(上个月)排行榜数据到db中
    @XxlJob("savePointsBoard2DB")//任务名字要和 xxljob控制台 任务的jobhandler值保持一致
    public void savePointsBoard2DB(){
        //1.获取上月的当前时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        //2.查询赛季表，获取上赛季信息
        PointsBoardSeason one = seasonService.lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, time)
                .ge(PointsBoardSeason::getEndTime, time)
                .one();
        if(one==null){
            return;
        }
        //3.计算动态表名 并存入threadlocal
        String tableName = LearningConstants.POINTS_BOARD_TABLE_PREFIX + one.getId();
        TableInfoContext.setInfo(tableName);
        //4.分页获取redis上赛季积分排行榜数据
        String format = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;
        int pageNo = 1;
        int PageSize = 1000;
        while(true){
            List<PointsBoard> pointsBoardList = pointsBoardService.queryCurrentBoard(key, pageNo, pageNo);
            if(CollUtils.isEmpty(pointsBoardList)){
                break;
            }
            pageNo++;
            //5.持久化到相应的赛季表中 批量新增
            for (PointsBoard pointsBoard : pointsBoardList) {
                pointsBoard.setId(Long.valueOf(pointsBoard.getRank()));//历史赛季排行榜中id就代表了排名
                pointsBoard.setRank(null);//排名字段不需要了
            }
            pointsBoardService.saveBatch(pointsBoardList);
        }
        //6.清空treadlocal中的数据
        TableInfoContext.remove();
    }
    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointBoardFromRedis(){
        //1.获取上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        //2.计算key
        String format = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;
        //3.删除
        redisTemplate.unlink(key);//删除大量的键用unlink比delete更合适，而且unlink不会阻塞进程，他是异步的
    }
}
